using System;
using System.Diagnostics.CodeAnalysis;

namespace Pinwheel.LSerialize.Formatters
{
    internal sealed unsafe class ErrorSerializeFormatter : ILFormatter
    {
        readonly Type type;
        readonly string message;

        public ErrorSerializeFormatter(Type type)
        {
            this.type = type;
            this.message = null;
        }

        public ErrorSerializeFormatter(Type type, string message)
        {
            this.type = type;
            this.message = message;
        }

        public void Serialize(LSerializeContext* context, LStreamWriter* writer, ref object value)
        {
            Throw();
        }

        public void Deserialize(LSerializeContext* context, LStreamReader* reader, ref object value)
        {
            Throw();
        }

        [DoesNotReturn]
        void Throw()
        {
            if (message != null)
            {
                LSerializeException.ThrowMessage(message);
            }
            else
            {
                LSerializeException.ThrowNotRegisteredInProvider(type);
            }
        }
    }
    
    internal sealed unsafe class ErrorSerializeFormatter<T> : LFormatter<T>
    {
        readonly Exception exception;
        readonly string message;
        
        public ErrorSerializeFormatter()
        {
            this.exception = null;
            this.message = null;
        }

        public ErrorSerializeFormatter(Exception exception)
        {
            this.exception = exception;
            this.message = null;
        }

        public ErrorSerializeFormatter(string message)
        {
            this.exception = null;
            this.message = message;
        }

        public override void Serialize(LSerializeContext* context, LStreamWriter* writer, ref T value)
        {
            Throw();
        }

        public override void Deserialize(LSerializeContext* context, LStreamReader* reader, ref T value)
        {
            Throw();
        }
        
        [DoesNotReturn]
        void Throw()
        {
            if (exception != null)
            {
                LSerializeException.ThrowRegisterInProviderFailed(typeof(T), exception);
            }
            else if (message != null)
            {
                LSerializeException.ThrowMessage(message);
            }
            else
            {
                LSerializeException.ThrowNotRegisteredInProvider(typeof(T));
            }
        }
    }
}

